// TCHotKey.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

// Global Variables:

ATOM tcHotkeyID;
ATOM vimHotkeyID;
HWND tcWinHwnd;
HWND vimWinHwnd;

void RunApplication(LPTSTR path,LPTSTR className,HWND& winHwnd);
void ShowOrHideWindows(HWND& winHwnd,bool fullScreen);
bool RegHotKey(LPTSTR atomStr,ATOM& idHotKey,UINT hotKey);
int APIENTRY _tWinMain(HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPTSTR    lpCmdLine,
					   int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);
	//read config from registry
	TCHAR tcPath[MAX_PATH]={0};
	TCHAR vimPath[MAX_PATH]={0};
	HKEY hKey;
	DWORD dwType;
	DWORD dwLength;
	TCHAR tcKey[2]={0};
	TCHAR vimKey[2]={0};
	TCHAR tcFullScreen[2]={0};
	TCHAR vimFullScreen[2]={0};
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SOFTWARE\\TVHotKey"),0,KEY_READ,&hKey)==ERROR_SUCCESS)
	{
		if(RegQueryValueEx(hKey,TEXT("TCPath"),NULL,&dwType,(LPBYTE)tcPath,&dwLength)!=ERROR_SUCCESS)
		{
			RegCloseKey(hKey);
			return -1;
		}
		if(RegQueryValueEx(hKey,TEXT("VIMPath"),NULL,&dwType,(LPBYTE)vimPath,&dwLength)!=ERROR_SUCCESS)
		{
			RegCloseKey(hKey);
			return -1;
		}
		if(RegQueryValueEx(hKey,TEXT("TCKey"),NULL,&dwType,(LPBYTE)tcKey,&dwLength)!=ERROR_SUCCESS)
		{
			_tcscpy_s(tcKey,2,TEXT("Q"));
		}
		if(RegQueryValueEx(hKey,TEXT("VIMKey"),NULL,&dwType,(LPBYTE)vimKey,&dwLength)!=ERROR_SUCCESS)
		{
			_tcscpy_s(vimKey,2,TEXT("V"));
		}
		RegQueryValueEx(hKey,TEXT("TCFullScreen"),NULL,&dwType,(LPBYTE)tcFullScreen,&dwLength);
		RegQueryValueEx(hKey,TEXT("VIMFullScreen"),NULL,&dwType,(LPBYTE)vimFullScreen,&dwLength);
		RegCloseKey(hKey);
	}

	//register the hotkey
	if (!RegHotKey(TEXT("TotalCommander's HotKey"),tcHotkeyID,tcKey[0])||!RegHotKey(TEXT("VIM's HotKey"),vimHotkeyID,vimKey[0]))
	{
		return -1;
	}
	MSG msg;	
	
	// process the hotkey message:
	while (GetMessage(&msg, NULL, 0, 0))
	{

		TranslateMessage(&msg);
		DispatchMessage(&msg);
		if (msg.message == WM_HOTKEY)
		{
			if(msg.wParam == tcHotkeyID){
				RunApplication(tcPath,TEXT("TTOTAL_CMD\0"),tcWinHwnd);
				ShowOrHideWindows(tcWinHwnd,tcFullScreen[0]);
			}else if (msg.wParam==vimHotkeyID)
			{
				RunApplication(vimPath,TEXT("Vim\0"),vimWinHwnd);
				ShowOrHideWindows(vimWinHwnd,vimFullScreen[0]);
			}
		}
	}
	if (tcHotkeyID!=0)
	{
		UnregisterHotKey(NULL,tcHotkeyID);
		GlobalDeleteAtom(tcHotkeyID);
	}
	if (vimHotkeyID!=0)
	{
		UnregisterHotKey(NULL,vimHotkeyID);
		GlobalDeleteAtom(vimHotkeyID);
	}
	return (int) msg.wParam;
}
bool RegHotKey(LPTSTR atomStr,ATOM& idHotKey,UINT hotKey){
	if((idHotKey =GlobalFindAtom(atomStr)) != 0) 
	{ 
		UnregisterHotKey(NULL,idHotKey);
		GlobalDeleteAtom(idHotKey);
	}
	idHotKey = GlobalAddAtom(atomStr);
	if(!RegisterHotKey(NULL, idHotKey, MOD_WIN, hotKey)){
		GlobalDeleteAtom(idHotKey);
		idHotKey=0;
		return false;
	}
	return true;
}
void RunApplication(LPTSTR path,LPTSTR className,HWND& winHwnd){
	if (winHwnd == NULL || !IsWindow(winHwnd))
	{
		if ((winHwnd = FindWindow(className, NULL)) == NULL)
		{
			STARTUPINFO si;
			PROCESS_INFORMATION pi;

			ZeroMemory( &si, sizeof(si) );
			si.cb = sizeof(si);
			ZeroMemory( &pi, sizeof(pi) );

			// Start the child process. 
			if( !CreateProcess( path,   // No module name (use command line)
				path,        // Command line
				NULL,           // Process handle not inheritable
				NULL,           // Thread handle not inheritable
				FALSE,          // Set handle inheritance to FALSE
				0,              // No creation flags
				NULL,           // Use parent's environment block
				NULL,           // Use parent's starting directory 
				&si,            // Pointer to STARTUPINFO structure
				&pi )           // Pointer to PROCESS_INFORMATION structure
				) 
			{
				_tprintf( TEXT("CreateProcess failed (%d)\n"), GetLastError() );
				return;
			}
			// Close process and thread handles. 
			CloseHandle( pi.hProcess );
			CloseHandle( pi.hThread );
		}
	}
}
void ShowOrHideWindows(HWND& winHwnd,bool fullScreen){
	if (winHwnd != NULL)
	{	
		if (IsWindowVisible(winHwnd))
		{
			SendMessage(winHwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
			ShowWindow(winHwnd, SW_HIDE);								
		}
		else
		{
			SendMessage(winHwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
			if (fullScreen)
			{
				LONG winLong=GetWindowLong(winHwnd,GWL_STYLE);
				if (winLong&WS_CAPTION)
				{
					SetWindowLong(winHwnd,GWL_STYLE,winLong&~WS_CAPTION);
				}
				MoveWindow(winHwnd,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),false);
			}
			SetForegroundWindow(winHwnd);
		}
	}
}